package org.papervision3d.objects
{
	import org.papervision3d.events.MouseEvent3D;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import org.papervision3d.core.geom.Vertex3D;
	
	public class DraggableObject3D extends DisplayObject3D
	{
		
		public var locked : Boolean = false;
		
		public function DraggableObject3D( name : String , initObject:Object = null):void
		{
			super( name , initObject );
			
			_build();
			
			addEventListener( MouseEvent.MOUSE_DOWN, onClick );
			addEventListener( MouseEvent.MOUSE_UP, onRelease );
		}
		
		override public function addChild(child:DisplayObject3D, name:String=null):DisplayObject3D {
			return subNode.addChild( child, name );
		}
		
		
		public function integrate( ) : void {
			
			vrY = ( destRotY - subNode.rotationY );
			vrX = ( destRotX - mainNode.rotationX );
			
			vrY *= 0.95;
			vrX *= 0.95;
			subNode.rotationY += vrY;
			mainNode.rotationX += vrX;
			
			while( mainNode.rotationX > 180 ) mainNode.rotationX -= 360;
			while( mainNode.rotationX < -180 ) mainNode.rotationX += 360;
			
			

		}
		
				
		/*_______________________________________________________________________________________________
		 * 		             																***	  PRIVATES
		 */
		 
		private var mainNode : DisplayObject3D;
		private var subNode : DisplayObject3D;
		
		protected var _currentOrientation : Number = 0;
		
		protected function set currentOrientation( val : Number ) : void {
			_currentOrientation = val;
		}
		protected function get currentOrientation() : Number {
			return _currentOrientation;
		}
		
		
		//____________________________________
		//							Dragging
		private var radius : Number;
		private var initMult : Number;
		private var haOff : Number;
		private var vaOff : Number;
		private var destRotY : Number = 0;
		private var destRotX : Number = 0;
		private var vrX : Number = 0;
		private var vrY : Number = 0;
		private var speedAtTransition : Number = 0;
		
		private function _build() : void {
			mainNode = new DisplayObject3D();
			subNode = new DisplayObject3D();
			mainNode.addChild( subNode );
			super.addChild( mainNode );
		}
		
		
		private function onClick( e : MouseEvent3D ) : void {
			if( !locked ) 
				startDrag(e);
		}
		private function onRelease( e : Event ) : void {
			currentOrientation = Math.round( subNode.rotationY / 90);
			stopDrag();
		}
		
		private function startDrag(e : MouseEvent3D ) : void {
			e.stopPropagation();
			var v : Vertex3D = e.position;
			//if( v.z > 0 ) return;

			destRotY = subNode.rotationY;
			destRotX = mainNode.rotationX;
			
			var dqrt : Number = Math.sqrt( v.x*v.x + v.y*v.y );
			radius = Math.sqrt( v.z*v.z + dqrt*dqrt );
			haOff = Math.atan2( - v.z, -v.x ) + (subNode.rotationY / 360 * (Math.PI * 2));
			vaOff = Math.atan2( - v.z, -v.y ) + (mainNode.rotationX / 360 * (Math.PI * 2));
			initMult = -v.z / Math.abs( v.z );
			
			addEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
			container.stage.addEventListener( MouseEvent.MOUSE_UP, onRelease);
			container.addEventListener( MouseEvent.ROLL_OUT, onRelease);
		}
		private function stopDrag() : void {
			removeEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
			container.stage.removeEventListener( MouseEvent.MOUSE_UP, onRelease);
			container.removeEventListener( MouseEvent.ROLL_OUT, onRelease);
			
			speedAtTransition = Math.abs( vrY );
		}
		
		private function onMouseMove( e : MouseEvent3D ) : void {
			var v : Vertex3D = e.position;
			
			var ratio : Number = Math.sqrt( v.x*v.x + v.y*v.y ) / radius;
			var mult : Number = initMult * Math.cos( Math.asin( Math.max( -0.9, Math.min( 0.9, ratio ) ) ) );
			
			var ha : Number = Math.atan2( radius * mult, -v.x ) ;
			var va : Number = Math.atan2( radius * mult, -v.y ) ;
			
			destRotY = ( haOff-ha ) / (Math.PI * 2) * 360;
			destRotX = ( vaOff-va ) / (Math.PI * 2) * 360;
			
			
			//trace( e.position.x );
			integrate();
		}
	}
}